<?php

namespace app\api\controller;

use app\admin\model\Alibaba;
use app\admin\model\Banner;
use app\admin\model\Category;
use app\admin\model\Cooperation;
use app\admin\model\Coupon;
use app\admin\model\Feedback;
use app\admin\model\Goods;
use app\admin\model\IndexMenu;
use app\admin\model\Notice;
use app\admin\model\Station;
use app\admin\model\UserCoupon;
use app\common\controller\Frontend;
use think\Collection;
use think\db\BaseQuery;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\exception\ValidateException;
use think\facade\Db;

class Index extends Frontend
{
    protected $noNeedLogin = [
        'getConfig',
        'banner',
        'category',
        'goods_list',
        'goods_detail',
        'getOilStationList',
        'getSmsCode',
        'getMenu',
        'license',
        'notice',
        'noticeDetail',
    ];
    /**
     * @var Category
     */
    private $categoryModel;

    public function initialize()
    {
        parent::initialize();
        $this->categoryModel = new Category();
    }

    public function getConfig()
    {
        $this->success('', [
            'site' => [
                'site_name' => get_sys_config('site_name'),
                'record_number' => get_sys_config('record_number'),
                'version' => get_sys_config('version'),
                'cdn_url' => full_url(),
            ],
        ]);
    }

    /**
     * 幻灯片
     * @param Banner $banner
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function banner(Banner $banner)
    {
        $bannerList = $banner
            ->where(['switch' => 1])
            ->order('weight desc, id desc')
            ->limit(5)
            ->hidden(array_merge(['id'], $this->hidden))
            ->select()
            ->each(function ($item) {
                $item['image'] = full_url($item['image']);
                return $item;
            });
        $this->success('', $bannerList);
    }

    /**
     * 商品分类
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function category()
    {
        $pid = (int)$this->request->get('parent_id', 0);
        $categoryList = $this->getCategory($pid);
        $this->success('', $categoryList);
    }

    /**
     * @param int $pid
     * @return Category[]|array|Collection
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    protected function getCategory(int $pid = 0)
    {
        $category = $this->categoryModel->where([
            'switch' => 1,
            'category_id' => $pid,
        ])
            ->order('weight desc, id desc')
            ->hidden(array_merge(['category_id'], $this->hidden))
            ->select()
            ->each(function ($item) {
                $item['image'] = full_url($item['image']);
            });
        foreach ($category as $k => $v) {
            $category[$k]['children'] = $this->getCategory($v['id']);
        }
        return $category;
    }

    /**
     * 商品列表
     * @param Goods $goods
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function goods_list(Goods $goods)
    {
        $categoryId = (int)$this->request->get('category_id', 0);
        $page = (int)$this->request->get('page', 1);
        $page = $page <= 0 ? 1 : $page;
        $limit = (int)$this->request->get('limit', 10);
        $limit = $limit <= 0 ? 1 : $limit;
        $best = (int)$this->request->get('best', 0);
        $new = (int)$this->request->get('new', 0);
        $kwd = $this->request->get('kwd', '');
        $kwd = trim($kwd);
        $cateIds = $this->getChildCateId($categoryId);
        $goodsList = $goods
            ->when(count($cateIds) > 0, function (BaseQuery $query) use ($cateIds) {
                $query->whereIn('category_id', $cateIds);
            })
            ->when($new, function (BaseQuery $query) {
                $query->where('new_switch', 1);
            })
            ->when($best, function (BaseQuery $query) {
                $query->where('best_switch', 1);
            })
            ->when($kwd != '', function (BaseQuery $query) use ($kwd) {
                $query->whereLike('goods_name', "%{$kwd}%");
            })
            ->where('switch', 1)
            ->order('best_switch desc, weight desc, id desc')
            ->field('id,goods_name,slider_images,sales,virtual,stock,commission1,commission2,commission3,price,integral,post_price,old_price,vip_price,best_switch')
            ->page($page)
            ->limit($limit)
            ->select()
            ->each(function ($item) {
                $sliders = [];
                foreach ($item['slider_images'] as $v) {
                    $sliders[] = full_url($v);
                }
                $item['slider_images'] = $sliders;
                return $item;
            });
        $this->success('', $goodsList);
    }

    /**
     * 商品详情
     * @param Goods $goods
     * @param Coupon $coupon
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function goods_detail(Goods $goods, Coupon $coupon)
    {
        $id = (int)$this->request->get('id', 0);
        $goods = $goods
            ->where('id', $id)
            ->with(['attr'])
            ->hidden($this->hidden)
            ->find();
        if (!$goods) $this->error('商品不存在');
        $goods['attr_keys'] = json_decode($goods['attr_keys'], true);
        $attrKeys = [];
        if ($goods['attr_keys']) {
            foreach ($goods['attr_keys'] as $v) {
                unset($v['inputVisible']);
                $attrKeys[] = $v;
            }
        }
        $goods['attr_keys'] = $attrKeys;
        $goods['slider_images'] = full_array_url($goods['slider_images']);
        $goods['content_images'] = full_array_url($goods['content_images']);
        $goods['attr'] = full_array_url($goods['attr'], 'image', $goods['slider_images'][0] ?? '');

        $time = time();
        $goods['coupon'] = $coupon
            ->whereIn('id', $goods['coupon_ids'])
            ->whereRaw("(coupon_type=0 and end_time>{$time}) or coupon_type=1")
            ->hidden(array_merge($this->hidden))
            ->select();
        $this->success('', $goods);
    }

    /**
     * @param int $cateId
     * @return array|int[]
     */
    protected function getChildCateId($cateId = 0)
    {
        if ($cateId == 0) return [];
        $cate = $this->categoryModel->where(['category_id' => $cateId])->column('id');
        $ids = [$cateId];
        foreach ($cate as $id) {
            $ids = array_merge($ids, $this->getChildCateId($id));
        }
        return $ids;
    }

    public function cooperation(Cooperation $cooperation)
    {
        $data = $this->request->post();
        $data['user_id'] = $this->auth->getUserId();
        $cooperation->save($data);

        $this->success('申请成功');
    }

    /**
     * @param Cooperation $cooperation
     * @throws DbException
     */
    public function getCooperation(Cooperation $cooperation)
    {
        $limit = (int)$this->request->get('limit', 10);
        $limit = $limit <= 0 ? 10 : $limit;
        $list = $cooperation
            ->where('user_id', $this->auth->getUserId())
            ->order('id desc')
            ->hidden(['delete_time'])
            ->paginate($limit)
            ->each(function ($item) {
                $item['state_text'] = '';
                switch ($item['state']) {
                    case 0:
                        $item['state_text'] = '待审核';
                        break;
                    case 1:
                        $item['state_text'] = '审核通过';
                        break;
                    case 2:
                        $item['state_text'] = '审核不通过';
                        break;
                }
                return $item;
            });

        $this->success('', $list);
    }

    public function getOilStationList(Station $station)
    {
        $page = (int)$this->request->get('page', 1);
        $page = $page <= 0 ? 1 : $page;
        $limit = (int)$this->request->get('limit', 10);
        $limit = $limit <= 0 ? 10 : $limit;
        $limit = ($page - 1) * $limit . ',' . $limit;
        $kwd = $this->request->get('kwd', '');
        $kwd = trim($kwd);
        $lng = $this->request->get('lng', '');
        $lng = trim($lng);
        $lat = $this->request->get('lat', '');
        $lat = trim($lat);
        $oil = $this->request->get('oil', '');
        $oil = trim($oil);
        $oil = urldecode($oil);
        $order = $this->request->get('order', '');
        $order = trim($order);
        $table = $station->getTable();
        $where = '';
        if ($kwd) {
            $where .= " and (station_name like '%{$kwd}%' or address like '%{$kwd}%')";
        }
        if ($oil) {
            $where .= " and oil_array like '%{$oil}%'";
        }
        $orderBy = '';
        if ($order == 'distance' || !$order) {
            $orderBy = 'order by distance asc, price asc, weight desc, id desc';
        } elseif ($order == 'price') {
            $orderBy = 'order by price asc, distance asc, weight desc, id desc';
        }

        $sql = <<<SQL
SELECT
id,station_name,image,address,business,old_price,price,lat,lng,oil_array,
ifnull(
round(
6378.138 * 2 * asin(
sqrt(
pow( sin( ( {$lat} * pi( ) / 180 - lat * pi() / 180 ) / 2 ), 2 ) + cos( {$lat} * pi() / 180 ) * cos( lat * pi() / 180 ) * pow( sin( ( {$lng} * pi() / 180- lng * pi() / 180 ) / 2 ), 2 )
)
) * 1000
),
0
) distance
FROM
{$table}
where switch=1 {$where}
{$orderBy}
-- limit {$limit}
SQL;

        $list = Db::query($sql);
        foreach ($list as $k => $v1) {
            $oilArray = json_decode($v1['oil_array'], true);
            $list[$k]['oil_array'] = $oilArray;
            foreach ($oilArray as $v) {
                $p = explode('|', $v['key']);
                if ($p && $oil && isset($p[0]) && strstr($p[0], $oil)) {
                    $list[$k]['price'] = $p[1];
                    break;
                }
            }
        }
        if ($order == 'price') {
            $newList = [];
            foreach ($list as $v) {
                $newList[$v['price']] = $v;
            }
            ksort($newList);
            $list = array_values($newList);
        }

        $this->success('', $list);
    }

    public function getOilStation(Station $station)
    {
        $id = (int)$this->request->get('id', 0);
        $lng = $this->request->get('lng', '');
        $lng = trim($lng);
        $lat = $this->request->get('lat', '');
        $lat = trim($lat);
        if ($id <= 0) $this->error('参数错误');
        $table = $station->getTable();
        $sql = <<<SQL
SELECT
id,station_name,image,address,business,old_price,price,lat,lng,oil_array,
ifnull(
round(
6378.138 * 2 * asin(
sqrt(
pow( sin( ( {$lat} * pi( ) / 180 - lat * pi() / 180 ) / 2 ), 2 ) + cos( {$lat} * pi() / 180 ) * cos( lat * pi() / 180 ) * pow( sin( ( {$lng} * pi() / 180- lng * pi() / 180 ) / 2 ), 2 )
)
) * 1000
),
0
) distance
FROM
{$table}
where switch=1 and id={$id}
SQL;
        $data = Db::query($sql);
        if (!isset($data[0])) $this->error('数据不存在');
        $data[0]['oil_array'] = json_decode($data[0]['oil_array'], true);
        if ($data[0]['oil_array']) {
            foreach ($data[0]['oil_array'] as $k => $v) {
                $key = explode('|', $v['key']);
                $data[0]['oil_array'][$k]['key'] = $key[0] ?? '';
                $data[0]['oil_array'][$k]['price'] = $key[1] ?? 0.00;
            }
        }
        $this->success('', $data[0]);
    }

    public function feedback(Feedback $feedback)
    {
        $data = $this->request->post();
        $feedback->save([
            'user_id' => $this->auth->getUserId(),
            'desc' => $data['desc'],
            'images' => $data['images'],
            'mobile' => $data['mobile'],
            'username' => $data['username'],
            'state' => 0,
        ]);
        $this->success('感谢反馈，我们会尽快进行处理');
    }

    public function getSmsCode($type, $mobile, Alibaba $alibaba)
    {
        $code = rand(0, 9999);

        try {
            $res = $alibaba->send([
                'mobile' => $mobile,
                'data' => [
                    'code' => $code
                ]
            ]);

            if ($res->body->code != 'OK') {
                throw new ValidateException($res->body->message);
            }
        } catch (\Exception $e) {
            // todo 上线前取消
            $this->error($e->getMessage(), ['code' => $code, 'msg' => '发送失败，请使用临时验证码：' . $code]);
        }
        cache($type . $mobile, $code, 600);
        $this->success('发送成功，请注意查收', ['code' => $code]);
    }

    /**
     * @param IndexMenu $indexMenu
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getMenu(IndexMenu $indexMenu)
    {
        $menu = $indexMenu->where(['status' => 1])->order('weight desc, id desc')->select()->each(function ($item) {
            $item['image'] = full_url($item['image']);
        });
        $this->success('', $menu);
    }

    /**
     * @param Coupon $coupon
     * @return void
     * @throws DbException
     */
    public function getCouponList(Coupon $coupon)
    {
        $time = time();
        $list = $coupon
            ->whereRaw("(coupon_type = 0 && start_time < {$time} && end_time > {$time}) or coupon_type=1")
            ->paginate()
            ->each(function ($item) {
                $item['start'] = $item['start_time'] ? date('Y.m.d', strtotime($item['start_time'])) : '';
                $item['end'] = $item['end_time'] ? date('Y.m.d', strtotime($item['end_time'])) : '';
                $goods = Goods::whereIn('id', $item['goods_ids'])->field('id, goods_name, slider_images, price')->select();
                $userCoupon = new UserCoupon();
                $has = $userCoupon->where(['user_id' => $this->auth->getUserId(), 'coupon_id' => $item['id']])->count();
                $item['has'] = false;
                if ($has > 0) {
                    $item['has'] = true;
                }
                $item['goods'] = $goods;
                return $item;
            });

        $this->success('', $list);
    }

    public function getWithdrawal()
    {
        $data = [
            'min_withdrawal' => get_sys_config('min_withdrawal'),
            'max_withdrawal' => get_sys_config('max_withdrawal'),
            'withdrawal_times' => get_sys_config('withdrawal_times'),
            'withdrawal_ratio' => get_sys_config('withdrawal_ratio'),
        ];
        $this->success('', $data);
    }

    public function license()
    {
        $this->success('', get_sys_config('license'));
    }

    /**
     * @param Notice $notice
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function notice(Notice $notice)
    {
        $page = (int)$this->request->get('page', 1);
        $page = $page <= 0 ? 1 : $page;
        $limit = (int)$this->request->get('limit', 10);
        $limit = $limit <= 0 ? 1 : $limit;

        $list = $notice
            ->order('id desc')
            ->page($page)
            ->limit($limit)
            ->hidden(['content', 'status', 'weight', 'status', 'updatetime', 'delete_time'])
            ->select()
            ->each(function ($item) {
                $item['icon'] = full_url($item['icon']);
                return $item;
            });

        $this->success('', $list);
    }

    /**
     * @param Notice $notice
     * @param $id
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function noticeDetail(Notice $notice, $id)
    {
        $id = (int)$id;
        if ($id <= 0) $this->error('参数不合法');
        $notice = $notice
            ->where('id', $id)
            ->hidden(['status', 'weight', 'status', 'updatetime', 'delete_time'])
            ->find();
        $notice['icon'] = full_url($notice['icon']);

        $this->success('', $notice);
    }
}